<script setup lang="ts">
import { onMounted, onUnmounted, ref, watch } from 'vue'
import { init as initEChart, type ECharts } from 'echarts'
import {
  LengthUnit,
  LengthUnitSelect,
  LengthInput,
  notify,
  fromMeterConverter,
  lengthUnitName
} from '@/widgets'
import { getClimbProfileById } from '../climb-profile'
import { getDescentProfileById } from '../descent-profile'
const props = defineProps<{
  id: string
  stage: 'Climb' | 'Descent'
}>()
type ProfileItem = {
  alt: number
  time: number
  dist: number
}

type Profile = {
  maxAlt: number
  getItems(alt0: number, alt1: number): ProfileItem[]
}

type ProfileItemAttrKey = 'alt' | 'time' | 'dist'

const itemAttrs: { name: string; key: ProfileItemAttrKey }[] = [
  {
    name: '高度',
    key: 'alt'
  },
  {
    name: '时间',
    key: 'time'
  },
  {
    name: '距离',
    key: 'dist'
  }
]

const xAxisKey = ref<ProfileItemAttrKey>('dist')
const yAxisKey = ref<ProfileItemAttrKey>('alt')
const altUnit = ref<LengthUnit>(LengthUnit.M)
const distUnit = ref<LengthUnit>(LengthUnit.KM)
const alt0 = ref<number>(0)
const alt1 = ref<number>(1)

let profile: Profile
let itemList: ProfileItem[] = []
function initData() {
  if (props.stage == 'Climb') {
    profile = getClimbProfileById(props.id)!
    alt0.value = 0
    alt1.value = profile.maxAlt - 200
  } else {
    profile = getDescentProfileById(props.id)!
    alt0.value = profile.maxAlt - 200
    alt1.value = 0
  }
  updateData()
}

function updateData() {
  itemList = profile.getItems(alt0.value, alt1.value)
}

const chartEl = ref<HTMLDivElement>()
let chart: ECharts | null = null

function updateChart() {
  if (!chart) {
    return
  }
  chart.clear()
  const xFn = getAxisFn(xAxisKey.value)
  const yFn = getAxisFn(yAxisKey.value)

  chart.setOption({
    title: {
      left: 'right',
      text: `${props.id} ${props.stage === 'Climb' ? '爬升剖面' : '下降剖面'}`,
      subtext: `大气模型:\nISA\n`
    },
    tooltip: {
      axisPointer: { type: 'cross' }
    },
    xAxis: {
      name: getAxisName(xAxisKey.value),
      type: 'value',
      min: 'dataMin'
    },
    yAxis: {
      name: getAxisName(yAxisKey.value),
      type: 'value',
      min: 'dataMin'
    },
    series: [
      {
        type: 'line',
        name: 'profile',
        showSymbol: false,
        data: itemList.map((e) => [xFn(e), yFn(e)])
      }
    ]
  })
}

function getAxisName(key: ProfileItemAttrKey): string {
  if (key === 'time') {
    return '时间(min)'
  }
  if (key === 'dist') {
    return `距离(${lengthUnitName(distUnit.value)})`
  }
  return `高度(${lengthUnitName(altUnit.value)})`
}

function getAxisFn(key: ProfileItemAttrKey): (e: ProfileItem) => number {
  if (key === 'time') {
    return (e) => Math.floor((e.time * 100.0) / 60.0) / 100.0
  }
  if (key === 'dist') {
    const fn1 = fromMeterConverter(distUnit.value)
    return (e) => Math.floor(fn1(e.dist))
  }
  const fn1 = fromMeterConverter(altUnit.value)
  return (e) => Math.floor(fn1(e.alt))
}

onMounted(() => {
  initData()
  chart = initEChart(chartEl.value)
  updateChart()
})
onUnmounted(() => {
  chart?.dispose()
})
watch(altUnit, updateChart)
watch(distUnit, updateChart)
watch(xAxisKey, updateChart)
watch(yAxisKey, updateChart)

function calc() {
  if (isNaN(alt0.value) || isNaN(alt1.value)) {
    notify.error({ content: '输入高度错误' })
    return
  }
  if (props.stage === 'Climb' && alt0.value >= alt1.value) {
    notify.error({ content: '起始高度必须小于结束高度' })
    return
  }
  if (props.stage === 'Descent' && alt0.value <= alt1.value) {
    notify.error({ content: '起始高度必须大于结束高度' })
    return
  }
  updateData()
  updateChart()
}
</script>
<template>
  <div class="cmb-des-profile">
    <div class="row">
      <div class="txt-box col-5em">起始高度</div>
      <LengthInput class="col-8em" v-model="alt0" />
      <div class="txt-box col-5em" style="margin-left: 2em">结束高度</div>
      <LengthInput class="col-8em" v-model="alt1" />
      <button class="button is-primary" style="margin-left: 2em" @click="calc()">计算</button>
    </div>
    <hr />
    <div class="row">
      <div class="txt-box col-5em">高度单位</div>
      <LengthUnitSelect v-model="altUnit" :options="[LengthUnit.M, LengthUnit.FT]" />
      <div class="txt-box col-5em" style="margin-left: 2em">距离单位</div>
      <LengthUnitSelect
        v-model="distUnit"
        :options="[LengthUnit.M, LengthUnit.NM, LengthUnit.KM]"
      />
      <div class="txt-box col-2em" style="margin-left: 2em">x轴</div>
      <div class="select">
        <select v-model="xAxisKey">
          <option v-for="attr in itemAttrs" :value="attr.key">{{ attr.name }}</option>
        </select>
      </div>
      <div class="txt-box col-2em" style="margin-left: 2em">y轴</div>
      <div class="select">
        <select v-model="yAxisKey">
          <option v-for="attr in itemAttrs" :value="attr.key">{{ attr.name }}</option>
        </select>
      </div>
    </div>
    <div class="cdb-chart" ref="chartEl"></div>
  </div>
</template>
<style lang="scss">
@import '@/widgets/var';
.cmb-des-profile {
  hr {
    height: 1px;
    margin: 0.5em 0;
    border-bottom: 1px solid $border;
  }
  .cdb-chart {
    margin-top: 1em;
    width: 60em;
    height: 40em;
  }
}
</style>
